#pragma once

#include "Nodes/Defs.h"
#include <string>

template<class Node>
class ExplicitPrinter : protected NodeVisitor<Node>
{
	/// Result accumulator
    std::string m_result;

public:
    static inline std::string print(Node * node)
    {
    	ExplicitPrinter printer;
    	node->accept(&printer);
    	return printer.m_result;
    }

    inline void visitOr(typename NodeTraits<Node>::NodeOr * node)
    {
    	// Always put opening parenthesis
        m_result += "(";

        // Process first child
        node->getChild(0)->accept(this);

        // Process next children
        for(size_t i=1; i<node->getChildrenCount(); ++i)
        {
        	m_result += " | ";
            node->getChild(i)->accept(this);
        }

    	// Always put closing parenthesis
        m_result += ")";
    }

    void visitAnd(typename NodeTraits<Node>::NodeAnd * node)
    {
    	// Always put opening parenthesis
        m_result += "(";

        // Process first child
        node->getChild(0)->accept(this);

        // Process next children
        for(size_t i=1; i<node->getChildrenCount(); ++i)
        {
        	m_result += " & ";
            node->getChild(i)->accept(this);
        }

    	// Always put closing parenthesis
        m_result += ")";
    }

    void visitNot(typename NodeTraits<Node>::NodeNot * node)
    {
        m_result += "~";
        node->getChild(0)->accept(this);
    }

    void visitAtom(typename NodeTraits<Node>::NodeAtom * node)
    {
        m_result += node->getAtomText();
    }
};
